package com.yuyou.fn.platform.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.CriteriaUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.platform.constant.AdminIdEnum;
import com.yuyou.fn.platform.entity.SysUser;
import com.yuyou.fn.platform.mapper.SysUserMapper;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.platform.service.ISysUserService;
import com.yuyou.fn.platform.vo.SysUserQueryVo;
import com.yuyou.fn.platform.vo.SysUserSaveOrUpdateVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 *
 * SysUser 表数据服务层接口实现类
 *
 */
@Service
public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser,Long> implements ISysUserService {

    private static final Pattern MOBILE_PATTERN = Pattern.compile("1\\d{10}");

    private final String DEFAULT_PASSWORD = DigestUtils.md5Hex("yuyou123") ;


    @Resource
    private RedisTemplate<String,String> redisTemplate ;

    @Value("${dev.env}")
    private boolean dev;

    @Override
    public SysUser login(String username, String passwordMd5Hash) {

        Example<SysUser> userExample = SysUser.createExample();
        Example.Criteria criteria = userExample.createCriteria();
        criteria.andEqualTo("password", passwordMd5Hash);
      /*  if (MOBILE_PATTERN.matcher(username).matches()) {
            criteria.andEqualTo("phoneNo", username);
        } else {*/
        criteria.andEqualTo("username", username);
      /*  }*/

        SysUser one = findOneByExample(userExample);

        if(one == null ){
            return null ;
        }

        return  one;
    }

    @Override
    public Page<SysUser> findSysUserByQueryForPage(SysUserQueryVo sysUserQueryVo, DataPermission dataPermission, int pageNo, int pageSize) {

        Example<SysUser> example = SysUser.createExample();
        example.orderBy("createTime").desc() ;
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,sysUserQueryVo);
        //只有誉优公司才能管理系统用户
        if(dataPermission.getUserType() != 0 ){
            criteria.andCondition(" 1 <> 1");
        }

        return findPageByExample(example,pageNo , pageSize );
    }

    @Override
    public Page<SysUser> findSysUserPageByQuery(SysUserQueryVo sysUserQueryVo, int pageNo, int pageSize) {
        Example<SysUser> example = SysUser.createExample();
        example.orderBy("createTime").desc() ;
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,sysUserQueryVo);

        return findPageByExample(example,pageNo , pageSize );
    }

    @Override
    public void saveOrUpdateSysUser(SysUserSaveOrUpdateVo sysUserSaveOrUpdateVo) {
        SysUser sysUser = new SysUser();

        sysUserSaveOrUpdateVo.setPassword(null);
        BeanUtils.copyProperties(sysUser,sysUserSaveOrUpdateVo);
        fillExtraData(sysUser) ;

        if(sysUser.getUserId() == null ){
            sysUser.setStatus(1);
            sysUser.setPassword(DEFAULT_PASSWORD);
            sysUser.setCreateTime(TimeUtils.now());
            sysUser.setUpdateTime(TimeUtils.now());
            checkSysUser(sysUser);
            insertSelective(sysUser);
        }else{
            checkSysUser(sysUser);
            sysUser.setUpdateTime(TimeUtils.now());
            updateSelectiveById(sysUser);
        }
    }

    private void checkSysUser(SysUser sysUser) {
        Example<SysUser> example = SysUser.createExample();
        example.createCriteria().andEqualTo("username",sysUser.getUsername() );
        SysUser one = findOneByExample(example);

        if(one!= null && (one.getUserId() == null || !one.getUserId().equals(sysUser.getUserId())) ){
            throw new BusException("用户名重复");
        }

  /*      if (StringUtils.isNotEmpty(sysUser.getPhoneNo())){
            Example<SysUser> phoneCheck = SysUser.createExample();
            phoneCheck.createCriteria().andEqualTo("phoneNo",sysUser.getPhoneNo());
            SysUser phoneOne = findOneByExample(phoneCheck);
            if (phoneOne!=null  && (phoneOne.getUserId() == null || !phoneOne.getUserId().equals(sysUser.getUserId()))){
                throw new BusException("电话号码已存在");
            }
        }*/



    }

    private void fillExtraData(SysUser sysUser) {

    }

    @Override
    public void updateSysUserStatus(Long userId, Integer status) {

        if(status != 0 && status != 1 ){
            throw new IllegalArgumentException("invalid status");
        }

        SysUser sysUser = new SysUser() ;
        sysUser.setUserId(userId);
        sysUser.setStatus(status);
        updateSelectiveById(sysUser);

    }

    @Override
    @Transactional
    public void changePassword(Long userId, String oldPassword, String newPassword) {
        SysUser sysUser = findById(userId);
        if(!sysUser.getPassword().equals(oldPassword)){
            throw new BusException("原密码不正确");
        }

        ZSetOperations<String, String> zSet = redisTemplate.opsForZSet();

        String key = String.format("password:%d",userId );
        Long index = zSet.rank(key, newPassword);

        if(index != null ){
            throw new BusException("新密码不能跟以前使用的密码一样");
        }
        zSet.add(key,oldPassword,-System.currentTimeMillis());
        zSet.removeRange(key,5,-1 );

        SysUser update = new SysUser();
        update.setUserId(userId);
        update.setPassword(newPassword);
        updateSelectiveById(update);
    }

    @Override
    public int checkPasswordStatus(Long userId) {
        SysUser sysUser = findById(userId, "password","createTime");

        if(sysUser.getPassword().equals(DEFAULT_PASSWORD)){
            return 1 ;
        }

        ZSetOperations<String, String> zSet = redisTemplate.opsForZSet();

        String key = String.format("password:%d",userId );

        Set<ZSetOperations.TypedTuple<String>> set = zSet.rangeWithScores(key, 0, 0);

        long threshold  = TimeUnit.DAYS.toMillis(90);

        if(dev){
            threshold  = TimeUnit.DAYS.toMillis(90);
        }

        if(set == null || set.isEmpty() ){
            if(System.currentTimeMillis() - sysUser.getCreateTime().getTime() >  threshold ){
                return 2 ;
            }else{
                return 0 ;
            }
        }

        ZSetOperations.TypedTuple<String> last = set.iterator().next();
        if( System.currentTimeMillis() + last.getScore().longValue() > threshold ){
            return 2 ;
        }
        return 0;
    }

    @Override
    public void deleteUser(Long userId) {
        if (AdminIdEnum.YUYOU.id.equals(userId)){
            throw new BusException("誉优账号不可删除");
        }
        deleteById(userId);
    }

    @Override
    public SysUser findByUserName(String userName) {
        Example<SysUser> example=SysUser.createExample();
        example.createCriteria().andEqualTo("username",userName);
        return findOneByExample(example);
    }

    @Override
    public SysUser findByPhoneNo(String phoneNo) {
        Example<SysUser> example=SysUser.createExample();
        example.createCriteria().andEqualTo("phoneNo",phoneNo);
        return findOneByExample(example);
    }

    @Cacheable("cache_findByUserIdFromCache")
    @Override
    public SysUser findByUserIdFromCache(Long userId) {
        return findById(userId);
    }

    @Override
    public void changePassword(Long userId, String newPasswordMd5) {
        SysUser update = new SysUser();
        update.setUserId(userId);
        update.setPassword(newPasswordMd5);
        updateSelectiveById(update);
    }

    @Override
    public void createSysUserIfNeed(Long userId, String realName, String phoneNo, String username, Integer userType) {
        SysUser sysUser = findById(userId);
        if(sysUser == null ){
            sysUser  = new SysUser();
            sysUser.setRealName(realName);
            sysUser.setPhoneNo(phoneNo);
            sysUser.setUsername(username);
            sysUser.setUserType(userType);
            sysUser.setUserId(userId);
            sysUser.setStatus(1);
            sysUser.setPassword(DEFAULT_PASSWORD);
            sysUser.setCreateTime(TimeUtils.now());
            sysUser.setUpdateTime(TimeUtils.now());
            checkSysUser(sysUser);
            insertSelective(sysUser);
        }else{
            sysUser.setRealName(realName);
            sysUser.setPhoneNo(phoneNo);
            sysUser.setUpdateTime(TimeUtils.now());
            checkSysUser(sysUser);
            updateSelectiveById(sysUser);
        }
    }

    @Override
    public void resetDefaultPassword(Long userId) {
        SysUser sysUser=new SysUser();
        sysUser.setUserId(userId);
        sysUser.setPassword(DEFAULT_PASSWORD);
        this.updateSelectiveById(sysUser);
    }

    @Override
    public List<SysUser> findSysUserByStatus(Integer status) {
        Example<SysUser> example=SysUser.createExample();
        example.createCriteria().andEqualTo("status",status);
        return findListByExample(example);
    }
}